package net.vsame.url2sql.url.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletContext;

import net.vsame.url2sql.config.ConfigFactory;
import net.vsame.url2sql.helper.SqlHelper;
import net.vsame.url2sql.helper.Url2SqlContext;
import net.vsame.url2sql.helper.WebHelper;
import net.vsame.url2sql.render.JsonRender;
import net.vsame.url2sql.render.Render;
import net.vsame.url2sql.url.Interceptor;


public class UrlMapping {
	
	private static UrlMapping mapping = new UrlMapping();

	private Map<String, UrlConfig> urlSqlMap = new HashMap<String, UrlConfig>();
	private Map<String, Render> renderMap = new HashMap<String, Render>();
	private List<Interceptor> interceptors = new ArrayList<Interceptor>();
	
	private UrlMapping(){}
	
	public static UrlMapping getMapping(){
		return mapping;
	}
	
	/**
	 * 取得所有Url映射
	 * @return
	 */
	public Map<String, UrlConfig> getUrlSqlMap() {
		return urlSqlMap;
	}

	/**
	 * 根据Url取得Sql
	 * @param url
	 * @return
	 */
	public UrlConfig getConfig(String url){
		if(!url.startsWith("/")){
			url = "/" + url;
		}
		return urlSqlMap.get(url);
	}
	
	public void addUrlConfig(UrlConfig urlConfig){
		urlSqlMap.put(urlConfig.getUrl(), urlConfig);
	}
	
	public void addUrlConfig(Map<String, UrlConfig> map){
		urlSqlMap.putAll(map);
	}
	
	public void addInterceptor(Interceptor i){
		interceptors.add(i);
	}
	
	public void addInterceptor(List<Interceptor> is){
		interceptors.addAll(is);
	}
	
	public void registRender(String expandedName, Render render){
		expandedName = expandedName.replace(".", "");//扩展名不能包含[.]
		renderMap.put(expandedName, render);
	}
	
	public Render findRender(String expandedName){
		return renderMap.get(expandedName);
	}
	
	public void reload(ServletContext servletContext) {
		urlSqlMap.clear();
		interceptors.clear();
		renderMap.clear();
		
		registRender("json", new JsonRender());//设置JSON视图，拦截器的init方法亦可覆盖此实现
		
		//从配置文件中加载
		ConfigFactory.load(UrlMapping.mapping);
		interceptors.add(new ActionInterceptor());
		
		//加载拦截器中 初始化方法　
		for(Interceptor i : interceptors) {
			i.init(this, servletContext);
		}
	}
	
	public void destroy() {
		for(Interceptor i : interceptors) {
			i.destroy();
		}
	}
	
	public void invoke(){
		try{
			new Chain().next();
		}catch (Exception e) {
			Url2SqlContext c = WebHelper.getContext();
			try {
				c.getConn().rollback();//回滚
			} catch (Exception e1) {
			}
			
			
			if(c.hasError()){//已经包含错误了，无需理会异常
				return ;
			}
			
			//取得异常消息
			String msg = null;
			if(e.getCause() != null){
				msg = e.getCause().getMessage();
			}else {
				msg = e.getMessage();
			}
			
			if(e instanceof SqlHelper.ParamNotExistException) {
				//参数出错
				c.putError(-2, msg);
			}else {
				c.error(e, msg);
			}
			
		}
	}
	
	public class Chain {
		private int i = -1;
		public void next(){
			i++;
			if(i<interceptors.size()){
				interceptors.get(i).invoke(this);
			}
		}
	}

}
